package com.bigknow.appstore.proxy.entity;

import com.bigknow.appstore.common.util.StringUtils;
import com.bigknow.appstore.proxy.constant.ConstMessages;
import com.bigknow.appstore.proxy.enumerate.SecurityType;
import com.bigknow.appstore.proxy.util.UriAndUrlHelper;
import com.bigknow.appstore.web.console.app.Application;

import java.io.Serializable;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.bigknow.appstore.common.Assert.assertNotNull;

/**
 * proxy资源的信息
 * Created by chaos on 2016/9/12.
 */
public class ProxyResourceMeta implements Serializable {

    /**
     * 唯一id
     */
    private String id;

    /**
     * 对应的proxy代理服务器id
     */
    private String proxyMetaId;

    /**
     * 资源的名称，必须唯一
     */
    private String proxyResName;

    private String proxyVersion;

    private String proxyUri;

    private String sourceHost;

    private int sourcePort;

    private String sourceUrl;

    //项目路径,默认为空（根据sourceUrl自动解析）
    private String sourcePath = "";

    private boolean https = false;

    /**
     * 是否启用htmlbody元素的http完整路径转换功能，默认为关闭
     * 思路是利用cache进行完整http请求路径的查找（默认查找两级）
     * 具体见{@link com.bigknow.appstore.proxy.handler.dispatcher.ResponseDispatcherHandler}
     */
    private boolean useReponseDispatcher = false;

    /**
     * 默认页面编码，有些网页不会在http头中设置编码，会在html中设置编码，不开启useReponseDispatcher
     * 是没有问题的，开启后会造成编码混乱，这种情况下就需要设置编码了
     */
    private String defaultEncoding = "utf-8";

    private Map<SecurityType, SecurityMeta> securityMetaMap = new HashMap<>();

    public ProxyResourceMeta(String id, String proxyMetaId, String proxyResName
            , String proxyVersion, String sourceUrl) {
        this(id, proxyMetaId, proxyResName, proxyVersion, sourceUrl, false, null);
    }

    public ProxyResourceMeta(String id, String proxyMetaId, String proxyResName
            , String proxyVersion, String sourceUrl, boolean useReponseDispatcher) {
        this(id, proxyMetaId, proxyResName, proxyVersion, sourceUrl, useReponseDispatcher, ConstMessages.DEFAULT_ENCODING);//默认编码
    }

    public ProxyResourceMeta(String id, String proxyMetaId, String proxyResName
            , String proxyVersion, String sourceUrl, boolean useReponseDispatcher, String defaultEncoding) {
        this.id = id;
        this.proxyMetaId = proxyMetaId;
        this.proxyResName = proxyResName;
        this.proxyVersion = proxyVersion;
        this.proxyUri = "/" + proxyResName + "/" + proxyVersion;
        this.sourceUrl = sourceUrl;
        this.useReponseDispatcher = useReponseDispatcher;
        this.defaultEncoding = defaultEncoding;
        try {
            URL url = new URL(sourceUrl);
            if (url.getProtocol().equals("https")) setHttps(true);
            this.sourceHost = url.getHost();
            this.sourcePort = getPortFromUrl(url);
            this.sourcePath = UriAndUrlHelper.getStandardUri(url.getPath());
        } catch (MalformedURLException e) {
            throw new RuntimeException(e);
        }
    }

    public String getProxyMetaId() {
        return proxyMetaId;
    }

    public void setProxyMetaId(String proxyMetaId) {
        this.proxyMetaId = proxyMetaId;
    }

    public String getProxyUri() {
        return proxyUri;
    }

    public void setProxyUri(String proxyUri) {
        this.proxyUri = proxyUri;
    }

    public String getSourceHost() {
        return sourceHost;
    }

    public void setSourceHost(String sourceHost) {
        this.sourceHost = sourceHost;
    }

    public int getSourcePort() {
        return sourcePort;
    }

    public void setSourcePort(int sourcePort) {
        this.sourcePort = sourcePort;
    }

    public boolean isHttps() {
        return https;
    }

    public void setHttps(boolean https) {
        this.https = https;
    }

    public String getSourcePath() {
        return sourcePath;
    }

    public void setSourcePath(String sourcePath) {
        this.sourcePath = sourcePath;
    }

    public String getSourceUrl() {
        return sourceUrl;
    }

    public void setSourceUrl(String sourceUrl) {
        this.sourceUrl = sourceUrl;
    }

    public String getProxyVersion() {
        return proxyVersion;
    }

    public void setProxyVersion(String proxyVersion) {
        this.proxyVersion = proxyVersion;
    }

    public String getProxyResName() {
        return proxyResName;
    }

    public void setProxyResName(String proxyResName) {
        this.proxyResName = proxyResName;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    private int getPortFromUrl(URL url) {
        if (url.getPort() != -1) return url.getPort();
        else if (url.getDefaultPort() != -1) {
            return url.getDefaultPort();
        } else {
            if (url.getProtocol().equals("http")) return 80;
            else return 443;
        }
    }

    public boolean isUseReponseDispatcher() {
        return useReponseDispatcher;
    }

    public void setUseReponseDispatcher(boolean useReponseDispatcher) {
        this.useReponseDispatcher = useReponseDispatcher;
    }

    public String getDefaultEncoding() {
        return defaultEncoding;
    }

    public void setDefaultEncoding(String defaultEncoding) {
        this.defaultEncoding = defaultEncoding;
    }

    public Map<SecurityType, SecurityMeta> getSecurityMetaMap() {
        return securityMetaMap;
    }

    public void setSecurityMetaMap(Map<SecurityType, SecurityMeta> securityMetaMap) {
        this.securityMetaMap = securityMetaMap;
    }

    public static List<ProxyResourceMeta> toProxyResMetaList(List<Application> appList) {
        assertNotNull(appList);
        List<ProxyResourceMeta> list = new ArrayList<>();
        for (Application app : appList) {
            ProxyResourceMeta res = ProxyResourceMeta.toProxyResMeta(app);
            list.add(res);
        }
        return list;
    }

    /**
     * 将application转换为ProxyResourceMeta
     *
     * @param app
     * @return ProxyResourceMeta
     */
    public static ProxyResourceMeta toProxyResMeta(Application app) {
        ProxyResourceMeta res = new ProxyResourceMeta(app.getId(), app.getProxyMetaId(), app.getContext()
                , app.getVersion(), app.getIndexUrl(), app.isUseReponseDispatcher(), app.getDefaultEncoding());

        if (app.isUseCallTimesSec()) {
            SecurityMeta sm = new SecurityMeta();
            sm.setSecurityType(SecurityType.REC_CALL_TIMES_SEC);
            if (StringUtils.isNotBlank(app.getOneDayTimes()))
                sm.getPolicyAttrs().put(ConstMessages.ONE_DAY_TIMES, app.getOneDayTimes());
            if (StringUtils.isNotBlank(app.getOneMothTimes()))
                sm.getPolicyAttrs().put(ConstMessages.ONE_MOTH_TIMES, app.getOneMothTimes());
            if (StringUtils.isNotBlank(app.getOneYearTimes()))
                sm.getPolicyAttrs().put(ConstMessages.ONE_YEAR_TIMES, app.getOneYearTimes());
            res.getSecurityMetaMap().put(sm.getSecurityType(), sm);
        }
        if (app.isUseCallDatasSec()) {
            SecurityMeta sm = new SecurityMeta();
            sm.setSecurityType(SecurityType.REC_CALL_DATAS_SEC);
            if (StringUtils.isNotBlank(app.getOneDayVisits()))
                sm.getPolicyAttrs().put(ConstMessages.ONE_DAY_VISITS, app.getOneDayVisits());
            if (StringUtils.isNotBlank(app.getOneMothVisits()))
                sm.getPolicyAttrs().put(ConstMessages.ONE_MOTH_VISITS, app.getOneMothVisits());
            if (StringUtils.isNotBlank(app.getOneYearVisits()))
                sm.getPolicyAttrs().put(ConstMessages.ONE_YEAR_VISITS, app.getOneYearVisits());
            res.getSecurityMetaMap().put(sm.getSecurityType(), sm);
        }
        return res;
    }


    public static void main(String[] args) throws MalformedURLException {
        String url1 = "http://sssss/testddd/ddd/";
        String url2 = "https://www.baidu.com";

        URL u1 = new URL(url1);
        System.out.println("u1   " + u1.getDefaultPort());
        System.out.println("u1   " + u1.getProtocol());
        System.out.println("u1   " + u1.getPort());
        System.out.println("u1   " + UriAndUrlHelper.getStandardUri(u1.getPath()));

        URL u2 = new URL(url2);
        System.out.println("u2   " + u2.getDefaultPort());
        System.out.println("u2   " + u2.getProtocol());
        System.out.println("u2   " + u2.getPort());
        System.out.println("u2   " + UriAndUrlHelper.getStandardUri(u2.getPath()));
    }
}
